'use strict';

const fs = require('fs');
const path = require('path');
const sendToWormhole = require('stream-wormhole');
const uuidv1 = require('uuid/v1');

const fileSrv = require('../utility/fileSrv');
const dataConst = require('../constant/data-const');

const Controller = require('egg').Controller;

class UploaderController extends Controller {
    async uploadFile() {
        const { app, ctx } = this;

        let stream = null;
        try {
            stream = await ctx.getFileStream();
            const { fields, fieldname, filename } = stream;
            const { dirName } = fields;

            console.dir([fieldname, filename, dirName]);
            const resourceDir = path.join(app.resDir, dirName);
            fileSrv.createDir(resourceDir);

            const extName = path.extname(filename);
            const newFileName = uuidv1().replace(/-/g, '') + extName;
            const targetPath = path.join(resourceDir, newFileName);

            fs.writeFileSync(targetPath);
            const writeStream = fs.createWriteStream(targetPath);
            stream.pipe(writeStream);

            ctx.successResult({
                file: newFileName
            });
        } catch (error) {
            await sendToWormhole(stream);
            ctx.errorResult(error.message);
        }
    }

    async uploadMultiFile() {
        const { config, ctx } = this;
        const parts = ctx.multipart();
        let stream;
        const files = [];
        while ((stream = await parts()) != null) {
            if (stream.length) {
                // arrays are busboy fields
                console.dir(stream);
            } else {
                const { filename, fieldname, encoding, mime } = stream;
                if (!filename) {
                    // user click `upload` before choose a file,
                    // `stream` will be file stream, but `stream.filename` is empty
                    // must handler this, such as log error.
                    return;
                }
                // otherwise, it's a stream
                console.dir({fieldname, filename, encoding, mime});

                const extName = path.extname(filename);
                const fileName = uuidv1().replace(/-/g, '') + extName;
                const target = path.join(config.HOME, 'images', fileName);

                try {
                    fs.writeFileSync(target);
                    const writeStream = fs.createWriteStream(target);
                    stream.pipe(writeStream);
                    files.push(fileName);
                } catch (err) {
                    await sendToWormhole(stream);
                    throw err;
                }
            }
        }
        console.log('and we are done parsing the form!');

        ctx.successResult({
            files
        });
    }

    async uploadMeetingImage() {
        const { app, ctx, service } = this;

        let stream = null;
        try {
            stream = await ctx.getFileStream();
            const { fields, fieldname, filename } = stream;
            const { dirName, meetingId } = fields;

            console.dir([fieldname, filename, dirName, meetingId]);
            if (!dirName) {
                return ctx.errorResult('dirName missing');
            }
            if (!meetingId) {
                return ctx.errorResult('meetingId missing');
            }

            const resourceDir = path.join(app.resDir, dirName);
            fileSrv.createDir(resourceDir);

            const extName = path.extname(filename);
            const newFileName = uuidv1().replace(/-/g, '') + extName;
            const targetPath = path.join(resourceDir, newFileName);

            fs.writeFileSync(targetPath);
            const writeStream = fs.createWriteStream(targetPath);
            stream.pipe(writeStream);

            const result = await service.image.updateMeetingImageSrv(meetingId, resourceDir, newFileName);
            if (result) {
                ctx.successResult({
                    file: newFileName
                });
            } else {
                ctx.errorResult('image can not created');
            }
        } catch (error) {
            await sendToWormhole(stream);
            ctx.errorResult(error.message);
        }
    }

    async uploadAvatar() {
        const { app, ctx, service } = this;

        let stream = null;
        try {
            stream = await ctx.getFileStream();
            const { fields, fieldname, filename } = stream;
            const { userId } = fields;

            console.dir([fieldname, filename, userId]);
            if (!userId) {
                return ctx.errorResult('userId missing');
            }

            const resourceDir = path.join(app.resDir, fieldname, `avatar${userId}`);
            fileSrv.createDir(resourceDir);

            const extName = path.extname(filename);
            const newFileName = uuidv1().replace(/-/g, '') + extName;
            const targetPath = path.join(resourceDir, newFileName);

            fs.writeFileSync(targetPath);
            const writeStream = fs.createWriteStream(targetPath);
            stream.pipe(writeStream);

            const avatarResult = await service.image.updateUserAvatarSrv(userId, resourceDir, newFileName);
            if (avatarResult) {
                await service.member.editUserBaseSrv(userId, {avatar_verify: dataConst.verifyStateType.apply.value});
                await service.verify.setUserVerifyStateSrv(userId, dataConst.verifyType.avatar.value, dataConst.verifyStateType.apply.value);
                ctx.successResult({
                    file: newFileName
                });
            } else {
                ctx.errorResult('avatar can not updated');
            }
        } catch (error) {
            await sendToWormhole(stream);
            ctx.errorResult(error.message);
        }
    }

    async uploadPhoto() {
        const { app, ctx, service } = this;

        let stream = null;
        try {
            stream = await ctx.getFileStream();
            const { fields, fieldname, filename } = stream;
            const { userId } = fields;

            console.dir([fieldname, filename, userId]);
            if (!userId) {
                return ctx.errorResult('userId missing');
            }

            const resourceDir = path.join(app.resDir, fieldname, `photo${userId}`);
            fileSrv.createDir(resourceDir);

            const extName = path.extname(filename);
            const newFileName = uuidv1().replace(/-/g, '') + extName;
            const targetPath = path.join(resourceDir, newFileName);

            fs.writeFileSync(targetPath);
            const writeStream = fs.createWriteStream(targetPath);
            stream.pipe(writeStream);

            const result = await service.image.addMemberPhotoSrv(userId, resourceDir, newFileName);
            if (result) {
                ctx.successResult({
                    file: newFileName
                });
            } else {
                ctx.errorResult('photo can not created');
            }
        } catch (error) {
            await sendToWormhole(stream);
            ctx.errorResult(error.message);
        }
    }

    async uploadIdentity() {
        const { app, ctx, service } = this;

        let stream = null;
        try {
            stream = await ctx.getFileStream();
            const { fields, fieldname, filename } = stream;
            const { userId, imageType } = fields;

            console.dir([fieldname, filename, userId]);
            if (!userId) {
                return ctx.errorResult('userId missing');
            }

            const resourceDir = path.join(app.resDir, fieldname, `identity${userId}`);
            fileSrv.createDir(resourceDir);

            const extName = path.extname(filename);
            const newFileName = uuidv1().replace(/-/g, '') + extName;
            const targetPath = path.join(resourceDir, newFileName);

            fs.writeFileSync(targetPath);
            const writeStream = fs.createWriteStream(targetPath);
            stream.pipe(writeStream);

            const result = await service.image.addMemberIdentitySrv(userId, imageType, resourceDir, newFileName);
            if (result) {
                await service.member.editUserBaseSrv(userId, {identity_verify: dataConst.verifyStateType.apply.value});
                await service.verify.setUserVerifyStateSrv(userId, dataConst.verifyType.identity.value, dataConst.verifyStateType.apply.value);
                ctx.successResult({
                    file: newFileName
                });
            } else {
                ctx.errorResult('identity image can not created');
            }
        } catch (error) {
            await sendToWormhole(stream);
            ctx.errorResult(error.message);
        }
    }
}

module.exports = UploaderController;
